package cn.dvptech.remotemate.screenmirror.server;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

import cn.dvptech.remotemate.screenmirror.listener.OnConnectionStateChangeListener;
import cn.dvptech.remotemate.screenmirror.listener.OnFrameReceivedListener;
import cn.dvptech.remotemate.screenmirror.screenHelper.Constant;
import cn.dvptech.remotemate.screenmirror.screenHelper.FrameMessage;
import timber.log.Timber;


/**
 *    author  : ulongx
 *    website : www.dvptech.cn
 *    date    : 2024/7/21
 *    desc    :
 */
public class TcpServer implements OnTcpWriteListener {
    private ServerSocket serverSocket;
    private final int TCP_PORT = Constant.port;
    private volatile boolean isAccept = true;
    private OnFrameReceivedListener frameListener;
    private OnConnectionStateChangeListener mConnectListener;
    private AcceptH264MsgThread acceptH264MsgThread;
    private TcpWriteThread mWrite;
    private BufferedOutputStream out;
    private ISendQueue mSendQueue = new NormalSendQueue();

    public void startServer() {
        new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    serverSocket = new ServerSocket();
                    serverSocket.setReuseAddress(true);
                    InetSocketAddress socketAddress = new InetSocketAddress(TCP_PORT);
                    serverSocket.bind(socketAddress);
                    Timber.d( "TcpServer -> start server---- %s", socketAddress.getHostString());
                    while (isAccept) {
                        // 接受客户端
                        Socket socket = serverSocket.accept();
                        Timber.e("TcpServer -> accept a client");
                        // 接受线程
                        acceptH264MsgThread = new AcceptH264MsgThread(socket.getInputStream(), socket.getOutputStream(), frameListener, mConnectListener);
                        acceptH264MsgThread.start();
                        // 发送线程
                        out = new BufferedOutputStream(socket.getOutputStream());
                        mWrite = new TcpWriteThread(out, mSendQueue, TcpServer.this);
                        mWrite.start();
                    }

                } catch (Exception e) {
                    Timber.tag("TcpServer").e(e.toString());
                    mConnectListener.acceptTcpDisConnect(e);
                }

            }
        }.start();
    }

    public void setOnAccepttBuffListener(OnFrameReceivedListener listener) {
        this.frameListener = listener;
    }

    public void setOnTcpConnectListener(OnConnectionStateChangeListener listener) {
        this.mConnectListener = listener;
    }

    public void stopServer() {
        isAccept = false;
        this.frameListener = null;
        new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    if (mWrite != null) {
                        mWrite.shutDown();
                    }
                    if (out != null) {
                        out.close();
                    }
                    mSendQueue.stop();
                    if (acceptH264MsgThread != null) acceptH264MsgThread.shutdown();
                    if (serverSocket != null) serverSocket.close();
                    mConnectListener.acceptTcpDisConnect(null);
                } catch (IOException e) {
                    e.printStackTrace();
                    Timber.tag("TcpServer").e(e.toString());
                }
            }
        }.start();
    }


    @Override
    public void socketDisconnect() {
        Timber.e("TcpServer -> socketDisconnect");
        this.mConnectListener.acceptTcpDisConnect(new Exception("意外断开连接"));
    }

    /**
     * 发送字符串内容
     * @param message
     */
    public void sendMessage(String message){
        FrameMessage<String> msg = new FrameMessage(message, 1,FrameMessage.FRAME_TYPE_INTER_FRAME);
        mSendQueue.putFrame(msg);
    }
}
